package cn.linkey.flowserver.controller;

import cn.linkey.orm.dao.Rdb;
import cn.linkey.orm.dao.impl.RdbImpl;
import cn.linkey.orm.doc.Document;
import cn.linkey.orm.doc.impl.DocumentsUtil;
import cn.linkey.orm.factory.BeanCtx;
import cn.linkey.orm.util.Tools;
import cn.linkey.workflow.api.WorkFlow;
import cn.linkey.workflow.api.WorkFlowImpl;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;

/**
 * 流程引擎接口服务
 * add by alibao 202012
 * walkwithdream@163.com
 */
@RestController
public class FlowServer {

    // 注入数据源对象
    @Resource
    private DataSource dataSource;

    /**
     * 获取所有流程信息
     *
     * @return 流程JSON数组字符串
     * [{"FormNumber":"","NodeName":"测试流程","OtherProcessName":"","WF_OrUnid":"f27d7992052d5041e108f770123f57780980","formConfig":"{\"total\":2,\"rows\":[{\"name\":\"name\",\"lable\":\"姓名\",\"value\":\"\",\"required\":\"true\",\"inputtype\":\"text\",\"params\":\"\",\"readtype\":\"EDIT\",\"remark\":\"\"},{\"name\":\"phone\",\"lable\":\"电话\",\"value\":\"\",\"required\":\"\",\"inputtype\":\"text\",\"params\":\"\",\"readtype\":\"EDIT\",\"remark\":\"\"}]}","WF_AddName":"","WordTemplate":"","ExceedTime":"0","Folderid":"","Deptid":"","ArchiveTableName":"BPM_ArchivedData","ProcessNumber":"","Nodeid":"Process","Processid":"68ae8f3705ffa04ca708f28031e99aec5cc8","AutoArchive":"1","ProcessOwner":"","Status":"0","WF_Version":"1.0","ProcessStarter":"","WF_DocCreated":"2020-11-10 14:36:36","ExtNodeType":"Process","SortNum":"1001","WF_AddName_CN":"","SaveDataHistory":"0","FormNumberForMobile":"","PrintTemplate":"","ProcessReader":"","WF_LastModified":"2020-11-10 14:38:24","icons":"","ProcessDesigner":"","ExtendTableName":"xmldata","WF_Appid":"S029","NodeType":"Process"},{"FormNumber":"","NodeName":"含有会签流程","OtherProcessName":"","WF_OrUnid":"6b426bc2012190482409bec0b85182868d5a","formConfig":"{\"total\":2,\"rows\":[{\"name\":\"title\",\"lable\":\"名称\",\"value\":\"\",\"required\":\"true\",\"inputtype\":\"text\",\"params\":\"\",\"readtype\":\"EDIT\",\"remark\":\"\"},{\"name\":\"remarked\",\"lable\":\"备注\",\"value\":\"\",\"required\":\"false\",\"inputtype\":\"text\",\"params\":\"\",\"readtype\":\"EDIT\",\"remark\":\"\"}]}","WF_AddName":"","WordTemplate":"","ExceedTime":"0","Folderid":"","Deptid":"","ArchiveTableName":"BPM_ArchivedData","ProcessNumber":"AlibaoT003","Nodeid":"Process","Processid":"bafed41c07dd304dc30be4107b679b35a471","AutoArchive":"1","ProcessOwner":"","Status":"0","WF_Version":"1.0","ProcessStarter":"","WF_DocCreated":"2020-11-03 11:09:44","ExtNodeType":"Process","SortNum":"1002","WF_AddName_CN":"","SaveDataHistory":"0","FormNumberForMobile":"","PrintTemplate":"","ProcessReader":"","WF_LastModified":"2020-11-03 11:47:39","icons":"","ProcessDesigner":"","ExtendTableName":"xmldata","WF_Appid":"S029","NodeType":"Process"},{"FormNumber":"","NodeName":"含有分支流程","OtherProcessName":"","WF_OrUnid":"e224e9230819c048000be800da1785b50816","formConfig":"","WF_AddName":"","WordTemplate":"","ExceedTime":"0","Folderid":"","Deptid":"","ArchiveTableName":"BPM_ArchivedData","ProcessNumber":"AlibaoT002","Nodeid":"Process","Processid":"a09a4672024ec048ea09d700796b50d9f947","AutoArchive":"1","ProcessOwner":"","Status":"0","WF_Version":"1.0","ProcessStarter":"","WF_DocCreated":"2020-11-03 10:45:02","ExtNodeType":"Process","SortNum":"1001","WF_AddName_CN":"","SaveDataHistory":"0","FormNumberForMobile":"","PrintTemplate":"","ProcessReader":"","WF_LastModified":"2020-11-03 11:45:02","icons":"","ProcessDesigner":"","ExtendTableName":"xmldata","WF_Appid":"S029","NodeType":"Process"},{"FormNumber":"","NodeName":"直线测试流程","OtherProcessName":"","WF_OrUnid":"3341cc7409f80044980a9a40636a513ae31a","formConfig":"{\"total\":4,\"rows\":[{\"inputtype\":\"text\",\"lable\":\"姓名\",\"name\":\"name\",\"params\":\"\",\"readtype\":\"EDIT\",\"remark\":\"\",\"required\":\"true\",\"value\":\"\"},{\"inputtype\":\"text\",\"lable\":\"手机号\",\"name\":\"phone\",\"params\":\"\",\"readtype\":\"EDIT\",\"remark\":\"\",\"required\":\"true\",\"value\":\"\"},{\"inputtype\":\"checkbox\",\"lable\":\"性别\",\"name\":\"sex\",\"params\":\"\",\"readtype\":\"EDIT\",\"remark\":\"\",\"required\":\"false\",\"value\":\"\"},{\"inputtype\":\"text\",\"lable\":\"年龄\",\"name\":\"age\",\"params\":\"\",\"readtype\":\"EDIT\",\"remark\":\"\",\"required\":\"false\",\"value\":\"\"}]}","WF_AddName":"","WordTemplate":"","ExceedTime":"0","Folderid":"","Deptid":"","ArchiveTableName":"BPM_ArchivedData","ProcessNumber":"AlibaoT001","Nodeid":"Process","Processid":"433c77e90c28204ed90a0d400d27774580ac","AutoArchive":"1","ProcessOwner":"","Status":"0","WF_Version":"1.0","ProcessStarter":"","WF_DocCreated":"2020-10-29 14:25:42","ExtNodeType":"Process","SortNum":"1001","WF_AddName_CN":"","SaveDataHistory":"0","FormNumberForMobile":"","PrintTemplate":"","ProcessReader":"","WF_LastModified":"2020-11-04 23:57:21","icons":"","ProcessDesigner":"","ExtendTableName":"xmldata","WF_Appid":"S029","NodeType":"Process"},{"FormNumber":"","NodeName":"固定资产流程","OtherProcessName":"","WF_OrUnid":"0aa56bea028b8044e70b5fc0c2b7cd1806ac","formConfig":"","WF_AddName":"","WordTemplate":"","ExceedTime":"0","Folderid":"","Deptid":"","ArchiveTableName":"BPM_ArchivedData","ProcessNumber":"TP_FIRST","Nodeid":"Process","Processid":"b9d23b3106510048cc08ffd0321ea0209bff","AutoArchive":"1","ProcessOwner":"dgw1833","Status":"0","WF_Version":"1.0","ProcessStarter":"","WF_DocCreated":"2020-09-24 19:36:35","ExtNodeType":"Process","SortNum":"1001","WF_AddName_CN":"","SaveDataHistory":"0","FormNumberForMobile":"","PrintTemplate":"","ProcessReader":"","WF_LastModified":"2020-10-15 19:26:07","icons":"","ProcessDesigner":"","ExtendTableName":"xmldata","WF_Appid":"S029","NodeType":"Process"}]
     */
    @RequestMapping(value = "/osflow/getProcessMsg", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
    public JSONObject getProcessMsg() {
        // 获取数据源
        Connection conn = null;
        JSONObject jsonObj = new JSONObject();
        JSONArray processMsg = new JSONArray();

        try {
            conn = dataSource.getConnection();
            WorkFlow workFlow = new WorkFlowImpl(conn);

            processMsg = workFlow.getProcessMsg();
            jsonObj.put("data", processMsg);

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        jsonObj.put("code", 20000);
        jsonObj.put("msg", "");

        return jsonObj;
    }

    /**
     * 打开流程初始化
     *
     * @param userid    用户唯一ID
     * @param processid 流程ID
     * @param docUnid   文档ID，当新启动流程时，docUnid的值为start
     * @return 返回需要初始化信息
     */
    @RequestMapping(value = "/osflow/openProcess/{userid}/{processid}/{docUnid}", method = RequestMethod.GET)
    public JSONObject openProcess(@PathVariable("userid") String userid, @PathVariable("processid") String processid, @PathVariable("docUnid") String docUnid) {

        // 特殊处理，当新启动流程时，docUnid的值为start，实际传入值因为空
        if ("start".equals(docUnid)) {
            docUnid = "";
        }
        // 当流程ID为0时，视为不传processid
        if (Tools.isNotBlank(docUnid) && "0".equals(processid)) {
            processid = "";
        }


        // 获取数据源
        Connection conn = null;
        JSONObject jsonObj = new JSONObject();

        try {
            conn = dataSource.getConnection();
            WorkFlow workFlow = new WorkFlowImpl(conn);

            JSONObject openInitJson = workFlow.openProcess(docUnid, processid, userid);
            jsonObj.put("data", openInitJson);
//            result = openInitJson.toJSONString();

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        jsonObj.put("code", 20000);
        jsonObj.put("msg", "");

        return jsonObj;
    }


    /**
     * 启动或提交流程
     *
     * @param config 流程提交参数
     * @return 审批结果格式：{"msg":"文档成功给环节(人事审批)用户(hanfeizi)进行处理!","Status":"ok"}  错误：{"msg":"文档已被其他用户处理或者您没有处理权限!","Status":"ok"}
     * @ processid        流程ID，流程启动时必填，其他情况可为空；可由getProcessMsg或openProcess接口获得；
     * @ docUnid          文档ID，也叫流程实例ID，流程启动时为空，其他情况必填；可由openProcess接口获得；
     * @ taskid           用户实例ID，选填，一般情况可传空，可由openProcess接口获得；
     * @ action           动作ID，GoToFirstNode、GoToOthers、EndUserTask、BackToDeliver、ReturnToAnyNode、BackToReturnUser、GoToAnyNode、GoToPrevUser、GoToPrevNode、GoToArchived、GoToNextParallelUser、GoToNextNode
     * @ currentNodeid    当前节点ID
     * @ nextNodeid       下一个节点ID，多个时逗号隔开；
     * @ nextUserList     下一个节点处理人，多个时逗号隔开，支持格式： ①user01,user02  ②user01$T10003,user02$T10002
     * @ copyUserList     传阅用户
     * @ userid           必填，必须是当前审批用户；可由userTodo或getApprovalInfo接口获得；
     * @ remark           流转记录
     * @ isBackFlag       选填，一般为空，只有回退动作时才需要填写，当为回退任意环节时，isBackFlag值可以为2，表示回退后需要直接返回给回退者；其余回退情况值为1；
     * @ reassignmentFlag 选填，一般为空，只有转交时才需要填写，需要转交者返回的标记1表示不需要，标记2表示需要；
     * @ formData         选填，JSONObject格式的字符串数据；
     */
    @RequestMapping(value = "/osflow/submitProcess", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public JSONObject submitProcess(@RequestBody JSONObject config) {

        String processid = (String) config.get("processid");
        String docUnid = (String) config.get("docUnid");
        String taskid = (String) config.get("taskid");
        String action = (String) config.get("action");
        String currentNodeid = (String) config.get("currentNodeid");
        String nextNodeid = (String) config.get("nextNodeid");
        String nextUserList = (String) config.get("nextUserList");
        String copyUserList = (String) config.get("copyUserList");
        String userid = (String) config.get("userid");
        String remark = (String) config.get("remark");
        String isBackFlag = (String) config.get("isBackFlag");
        String reassignmentFlag = (String) config.get("reassignmentFlag");
        String formData = (String) config.get("maindata");

        // 获取数据源
        Connection conn = null;
        String result = "";
        JSONObject jsonObj = new JSONObject();

        try {
            conn = dataSource.getConnection();
            WorkFlow workFlow = new WorkFlowImpl(conn);
            JSONObject maindata = JSONObject.parseObject(formData);

            result = workFlow.runProcess(processid, docUnid, taskid, action, currentNodeid,
                    nextNodeid, nextUserList, copyUserList, userid, remark, isBackFlag, reassignmentFlag, maindata);

            JSONObject resultJson = JSONObject.parseObject(result);

            jsonObj.put("code", 20000);
            jsonObj.put("msg", resultJson.getString("msg"));

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        return jsonObj;
    }


    /**
     * 获取审批过程信息
     * @param docUnid 文档ID
     * @return 返回审批信息
     */
    @RequestMapping("/osflow/getApprovalInfo/{docUnid}")
    public JSONObject getApprovalInfo(@PathVariable("docUnid") String docUnid) {
        // 获取数据源
        Connection conn = null;
        JSONObject jsonObj = new JSONObject();

        try {
            conn = dataSource.getConnection();
            WorkFlow workFlow = new WorkFlowImpl(conn);

            JSONObject approvalInfo = workFlow.getApprovalInfo(docUnid);
            jsonObj.put("data", approvalInfo);

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        jsonObj.put("code", 20000);
        jsonObj.put("msg", "");

        return jsonObj;
    }

    /**
     * 获取用户待办信息
     */
    @RequestMapping("/osflow/userTodo/{userid}")
    public JSONObject userTodo(@PathVariable("userid") String userid) {

        // 特殊处理，当useid只为all时，表示获取所有代办，此时userid设置为空
        if ("all".equals(userid)) {
            userid = "";
        }

        // 获取数据源
        Connection conn = null;
        JSONObject jsonObj = new JSONObject();

        try {
            conn = dataSource.getConnection();
            WorkFlow workFlow = new WorkFlowImpl(conn);

            JSONArray userToDOInfo = workFlow.getUserToDoInfo(userid);

            jsonObj.put("code", 20000);
            jsonObj.put("data", userToDOInfo);

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        return jsonObj;
    }


// 后续需要将以下方法更新为接口调用
// ==========================================================================================================================

    /**
     * 获得表单配置信息(用于表单设计器/解析器)
     *
     * @return {code:2000,msg:"",data:{}}
     */
    @RequestMapping(value = "/osflow/openFormDesigner", method = RequestMethod.GET)
    public JSONObject getFormDesignConfig(@RequestParam(name = "WF_Processid", required = false, defaultValue = "") String WF_Processid,
                                          @RequestParam(name = "WF_DocUnid", required = false, defaultValue = "") String WF_DocUnid,
                                          @RequestParam(name = "WF_Userid", required = true) String WF_Userid) {

//        FlowChart imp = new FlowchartImp();
        Connection conn = null;
        Rdb rdb;
        JSONObject jsonObj = new JSONObject();
        Document doc = null;
        JSONObject formConfigJSON = new JSONObject();

        Document mainDoc = null;

        try {
            conn = dataSource.getConnection();

            // 初始化连接
            rdb = new RdbImpl(conn);
            BeanCtx.setConnection(conn);
            BeanCtx.setRdb(rdb);

            mainDoc = rdb.getDocumentBySql("select * from bpm_alldocument where WF_OrUnid='" + WF_DocUnid + "'");

            if (Tools.isNotBlank(WF_DocUnid)) {
                String sql2 = "select WF_Processid from bpm_alldocument where WF_OrUnid='" + WF_DocUnid + "'";
                WF_Processid = rdb.getValueBySql(sql2);
            }

            if (Tools.isNotBlank(WF_Processid)) {
                String sql3 = "select * from bpm_modprocesslist where Processid='" + WF_Processid + "'";
                Document doc1 = rdb.getDocumentBySql(sql3);

                // 绑定表单模型判断
                if (Tools.isBlank(doc1.g("formModel"))) {
                    jsonObj.put("code", 50000);
                    jsonObj.put("data", "{}");
                    jsonObj.put("msg", "流程未绑定表单模型，请联系管理员！");
                    return jsonObj;
                }

                String sql4 = "select * from bpm_formlist where FormNumber = '" + doc1.g("formModel") + "'";
                doc = rdb.getDocumentBySql(sql4);

                WorkFlow workFlow = new WorkFlowImpl(conn);

                JSONObject openInitJson = workFlow.openProcess(WF_DocUnid, WF_Processid, WF_Userid);
                formConfigJSON.put("openFlowInit", openInitJson.toJSONString());
                JSONArray WF_NextNodeConfig = openInitJson.getJSONArray("WF_NextNodeConfig");
                JSONArray WF_CurrentNodeConfig = openInitJson.getJSONArray("WF_CurrentNodeConfig");

                // 下一个节点 [{label: "节点1", value: 1}, {label: "节点2", value: 2}]
                JSONArray nextNodeConfig = new JSONArray();
                for (int n = 0; n < WF_NextNodeConfig.size(); n++) {
                    JSONObject nextNodeTemp = new JSONObject();
                    nextNodeTemp.put("label", WF_NextNodeConfig.getJSONObject(n).getString("NodeName"));
                    nextNodeTemp.put("value", WF_NextNodeConfig.getJSONObject(n).getString("Nodeid"));
                    nextNodeConfig.add(nextNodeTemp);

                }

                JSONArray fieldConfigArr = JSONArray.parseArray(Tools.unEscapeEasyHtml(doc.g("FieldConfig")));
                JSONObject formConfJSON = JSONObject.parseObject(doc.g("formConf"));
                if("true" == formConfJSON.getString("approvalForm")){
                    String ApprovalFormStr = rdb.getValueBySql("select FieldConfig from bpm_formlist where FormNumber='ApprovalForm'");
                    JSONArray ApprovalFormArr = JSONArray.parseArray(ApprovalFormStr);
                    fieldConfigArr.add(ApprovalFormArr.getJSONObject(0));
                }

                for (int i = 0; i < fieldConfigArr.size(); i++) {
                    JSONObject filed1 = fieldConfigArr.getJSONObject(i);
                    JSONObject filedConf = filed1.getJSONObject("__config__");

                    // 审批处理单赋值
                    if ("ApprovalForm".equals(filedConf.getString("componentName"))) {
                        JSONArray filedChildArr = filedConf.getJSONArray("children");
                        for (int j = 0; j < filedChildArr.size(); j++) {
                            JSONObject filedchild1 = filedChildArr.getJSONObject(j);
                            JSONObject filedchildConf = filedchild1.getJSONObject("__config__");
//                            System.out.println(filedchild1.toJSONString());
                            switch (filedchild1.getString("__vModel__")) {
                                case "userid":
                                    filedchildConf.put("defaultValue", WF_Userid);
                                    break;
                                case "nextUserList":
                                    filedchildConf.put("defaultValue", WF_NextNodeConfig.getJSONObject(0).getString("SelectUseridList"));
                                    break;
                                case "nextNodeid":
                                    filedchild1.put("__slot__", JSONObject.parseObject("{options: " + nextNodeConfig.toJSONString() + "}"));
                                    if (nextNodeConfig.size() == 1) {
                                        filedchildConf.put("defaultValue", nextNodeConfig.getJSONObject(0).getString("value"));
                                    }
                                    break;
                                case "action":
                                    JSONArray btnConfigArr = JSONArray.parseArray(WF_CurrentNodeConfig.getJSONObject(0).getString("WF_Actionid"));
                                    filedchild1.put("__slot__", JSONObject.parseObject("{options: " + btnConfigArr + "}"));
                                    break;
                            }
                        }
                    }


                    // 主表单赋值
                    if (!mainDoc.isNull() && Tools.isNotBlank(mainDoc.g(filed1.getString("__vModel__")))) {
                        String fileddValue = mainDoc.g(filed1.getString("__vModel__"));
                        if (Tools.isNotBlank(filedConf.getString("dataConsumer"))) {
                            filedConf.put("defaultValue", JSONArray.parseArray(fileddValue));
                        } else {
                            filedConf.put("defaultValue", fileddValue);
                        }
                    }
                }

                formConfigJSON.put("isNew", 0);
                if (doc.isNull()) {
                    formConfigJSON.put("isNew", 1);
                }

                formConfigJSON.put("UIType", doc.g("UIType"));
                formConfigJSON.put("formConf", doc.g("formConf"));
                formConfigJSON.put("drawingItems", fieldConfigArr.toJSONString());
                formConfigJSON.put("idGlobal", doc.g("idGlobal"));

                jsonObj.put("code", 20000);
                jsonObj.put("data", formConfigJSON);
                jsonObj.put("msg", "");

            }

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        return jsonObj;
    }

    @RequestMapping(value = "/osflow/getFormMessage", method = RequestMethod.GET)
    public JSONObject getFormMessage(@RequestParam(name = "WF_Userid", required = false, defaultValue = "") String WF_Userid) {

        // 获取数据源
        Connection conn = null;
        JSONObject jsonObj = new JSONObject();
        Rdb rdb;

        try {
            conn = dataSource.getConnection();
            // 初始化连接
            rdb = new RdbImpl(conn);
            BeanCtx.setConnection(conn);
            BeanCtx.setRdb(rdb);

            String sql = "select * from bpm_formlist order by WF_DocCreated desc";
            Document[] docs = rdb.getAllDocumentsBySql(sql);
            JSONArray docsJsonArr = JSONArray.parseArray(DocumentsUtil.dc2json(docs, ""));

            jsonObj.put("code", 20000);
            jsonObj.put("data", docsJsonArr);
            jsonObj.put("msg", "");

        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtils.close(conn);
        }

        return jsonObj;
    }

    /**
     * 获取唯一id
     * @return {unid: ""}
     */
    @RequestMapping(value = "/osflow/getUnnid", method = RequestMethod.GET)
    public JSONObject getUnnid() {

        JSONObject jsonObj = new JSONObject();
        String unid = new RdbImpl().getNewUnid();

        jsonObj.put("code", 20000);
        jsonObj.put("data", JSONObject.parse("{unid: \"" + unid + "\"}"));
        jsonObj.put("msg", "");

        return jsonObj;
    }
}
